package com.dp.server.backend.servicios;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.h2.table.Plan;


import com.dp.server.IServiciosPaqueteImpl;
import com.dp.server.IServiciosVueloImpl;
import com.dp.server.MantenimientoGenerico;
import com.dp.server.entities.Paquete;
import com.dp.server.entities.PlanDeVuelo;
import com.dp.server.entities.ReservaVuelo;
import com.dp.server.entities.Vuelo;


public class AplicarCambiosFecha {
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	MantenimientoGenerico<ReservaVuelo> mRVuelo = new MantenimientoGenerico<>("ReservaVuelo");
	MantenimientoGenerico<Paquete> mPaquete = new MantenimientoGenerico<>("Paquete");
	MantenimientoGenerico<PlanDeVuelo> mPlan = new MantenimientoGenerico<>("PlanDeVuelo");
	MantenimientoGenerico<Vuelo> mVuelo = new MantenimientoGenerico<>("Vuelo");
	IServiciosVueloImpl servicio_vuelo = new IServiciosVueloImpl();
	IServiciosPaqueteImpl servicio_paquete = new IServiciosPaqueteImpl();
	Date sumaMinutos( Date fecha , int minutos ){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime( fecha );
		calendar.add( Calendar.MINUTE , minutos );
		return calendar.getTime();
	}
	
	List< Paquete > getPaquetes( Vuelo v ){
		List< Paquete> ans = new ArrayList<>();
		String query = "idVuelo = " + v.getId();
		List< ReservaVuelo > reserva = (List<ReservaVuelo>)MantenimientoGenerico.query("from ReservaVuelo where " + query);
		for( ReservaVuelo r : reserva ) ans.add( mPaquete.buscarID( r.getIdPaquete() ));
		return ans;
	}
	List< Vuelo > vuelos_despegan_en_hora( Date fecha ){
		Date ini = sumaMinutos( fecha , -30 );
		Date fin = sumaMinutos( fecha, 30 );
		String range = " fechaHoraSalida between '" + format.format( ini )  + "' and '" +  format.format(fin) + "'";
		List<Vuelo> vuelos = (List<Vuelo>)MantenimientoGenerico.query( "from Vuelo where " + range );
		return vuelos;
	}
	
	List< Vuelo > vuelos_aterrizan_en_hora( Date fecha ){
		Date ini = sumaMinutos( fecha , -30 );
		Date fin = sumaMinutos( fecha, 30 );
		String range = " fechaHoraLlegada between '" + format.format( ini )  + "' and '" +  format.format(fin) + "'";
		List<Vuelo> vuelos = (List<Vuelo>)MantenimientoGenerico.query( "from Vuelo where " + range );
		return vuelos;
	}
	public void levantar_paquetes( Date fecha ){
		List<Vuelo> vuelos = vuelos_despegan_en_hora( fecha );
		for( Vuelo v : vuelos ) {
			if( v.getIdEstado() != Vuelo.EN_ORIGEN ) continue;
			List< Paquete > paquetes = getPaquetes( v );
			for( Paquete p : paquetes ){
				if( p.getEstadoPaquete() != Paquete.ALMACEN ) continue;
				p.subirPaquete();
				mPaquete.modifica( p );
			}
		}
	}
	
	public void volar_vuelos( Date fecha ){
		List<Vuelo> vuelos = vuelos_despegan_en_hora(fecha);
		for( Vuelo v : vuelos ){
			if( v.getIdEstado() != Vuelo.EN_ORIGEN ) continue;
			servicio_vuelo.despegar( v , fecha );
		}
	}
	
	public void aterrizar_vuelos( Date fecha ){
		List<Vuelo> vuelos = vuelos_aterrizan_en_hora(fecha);
		for( Vuelo v : vuelos ){
			if( v.getIdEstado() != Vuelo.VOLANDO ) continue;
			servicio_vuelo.aterrizar( v , fecha );
		}		
	}
	public void entrar_a_almacen( Date fecha ){
		List<Vuelo> vuelos = vuelos_aterrizan_en_hora(fecha);
		for( Vuelo v : vuelos ){
			if( v.getIdEstado() != Vuelo.EN_DESTINO ) continue;
			List<Paquete> paquetes = getPaquetes(v);
			for (Paquete p : paquetes){
				servicio_paquete.MovimientoPaqueteAlmacen( p.extractDTO() );
			}
		}		
	}
	public void recoger_paquetes_destino( Date fecha ){
		List<Paquete> paquetes = (List<Paquete>)MantenimientoGenerico.query("from Paquete where almacenActual = almacenDestino and estadoPaquete < 4 ");
		for( Paquete p: paquetes ){
			PlanDeVuelo plan = mPlan.buscarID( p.getPlanDeVuelo() );
			if( plan != null ){
				plan.recoger();
				mPlan.modifica( plan );
			} 
			p.setFechaRealLlegada( fecha );
			p.setEstadoPaquete( 4 );
			mPaquete.modifica( p );
		}
	}
	
	public void ciclo_completo( Date fecha ){
		aterrizar_vuelos(fecha);
		entrar_a_almacen(fecha);
		recoger_paquetes_destino(fecha);
		levantar_paquetes(fecha);
		volar_vuelos(fecha);
	}
	
	public void cambio_en_rango( Date inicio , Date fin ){
		Calendar cal = Calendar.getInstance();
		cal.setTime( inicio );
		while( cal.getTime().compareTo( fin ) <= 0 ){
			ciclo_completo( cal.getTime() );
		}
	}
	
	public static void main( String [] args ) throws ParseException{
		AplicarCambiosFecha instance = new AplicarCambiosFecha();
		String date = "2012-11-30 20:00:00";
		Date target = format.parse(date);
		// instance.levantar_paquetes(target);
		// instance.volar_vuelos(target);
		// instance.aterrizar_vuelos(target);
		// instance.entrar_a_almacen(target);
		instance.recoger_paquetes_destino( target );
	}
}
